﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Ether;
using Ether.Libs;
using Firefly.Libs;
using Ether.Mapping;
using Jitter;

namespace Ether
{
    public abstract class Structure
    {
        protected class StructurePrim : PhysicsPrim
        {
            public StructurePrim(Vector3 pos)
                : base(pos)
            {
                this.IsStatic = false;
                this.AffectedByGravity = true;
                this.Rescale(Vector3.One);
            }

            public Matrix World
            {
                get
                {
                    return
                        Matrix.CreateScale(this.Scale)
                        *
                        Matrix.CreateRotationX(Rotation.X) *
                        Matrix.CreateRotationY(Rotation.Y) *
                        Matrix.CreateRotationZ(Rotation.Z)
                        *
                        Matrix.CreateTranslation(Conversion.ConvertVect(this.Position));
                }
            }
        }
        
        //Fields
        public World ParentWorld;
        public LevelMap ParentMap;
        protected StructurePrim StructBody;
                
        protected Model structureModel;
        protected Texture2D structureTexture;

        protected string structAssetHolder = null;
        protected string structureTextureHolder = null;

        public Jitter.Dynamics.RigidBody Body 
        {
            get { return StructBody; }
        }
        public StructureRenderMode RenderMode;

        protected bool OssilateY { get; set; }
        protected float OssilateYMultipler { get; set; }

        //Construct
        public Structure(LevelMap ParentMap, World ParentWorld, string structureAsset, string texture)
        {
            this.ParentWorld = ParentWorld;
            this.ParentMap = ParentMap;
            this.structAssetHolder = structureAsset;
            this.structureTextureHolder = texture;
            this.RenderMode = StructureRenderMode.Blueprint;
            this.OssilateY = false;
            this.OssilateYMultipler = .5f;
            ParentWorld.CollisionSystem.CollisionDetected += new Jitter.Collision.CollisionDetectedHandler(CollisionDetected);
        }
                 
        //Methods
        private void CollisionDetected(Jitter.Dynamics.RigidBody body1, Jitter.Dynamics.RigidBody body2, 
            Jitter.LinearMath.JVector point1, Jitter.LinearMath.JVector point2, Jitter.LinearMath.JVector normal, float penetration)
        {
            //If this body collisdes with anything, then disable physics
            if(body1 == StructBody || body2 == StructBody)
                DisablePhysics();
        }

        public void ChangeToTextureRender()
        {
            this.RenderMode = StructureRenderMode.Normal;
            this.StructBody.AffectedByGravity = true;
            this.StructBody.IsStatic = false;
        }   
        public void DisablePhysics()
        {
            this.StructBody.IsStatic = true;
            this.StructBody.AffectedByGravity = false;
        }

        public virtual void LoadStructure(Game game)
        {
            StructBody = new StructurePrim(Vector3.Zero);
            structureModel = Resources.LoadModel(game, ref Resources.StructureShader, structAssetHolder);
            structureTexture = game.Content.Load<Texture2D>(structureTextureHolder);
        }
        public void DrawStructure(Camera camera, GameTime time)
        {
            Matrix[] transforms = new Matrix[structureModel.Bones.Count];
            structureModel.CopyAbsoluteBoneTransformsTo(transforms);
            foreach (ModelMesh mesh in structureModel.Meshes)
            {
                foreach (Effect fx in mesh.Effects)
                {
                    if (RenderMode == StructureRenderMode.Blueprint)
                        fx.CurrentTechnique = fx.Techniques["BlueprintShade"];
                    else
                        fx.CurrentTechnique = fx.Techniques["TextureShade"];

                    fx.Parameters["World"].SetValue(transforms[mesh.ParentBone.Index] * StructBody.World);
                    fx.Parameters["View"].SetValue(camera.View);
                    fx.Parameters["Projection"].SetValue(camera.Projection);
                    fx.Parameters["StructureTexture"].SetValue(this.structureTexture);

                    fx.Parameters["AmbientColor"].SetValue(EtherEngine.AmbientColor);
                    fx.Parameters["AmbientLevel"].SetValue(EtherEngine.AmbientLevel);

                    fx.Parameters["OssilateY"].SetValue(this.OssilateY);
                    fx.Parameters["OssilateYMultipler"].SetValue(this.OssilateYMultipler);
                    fx.Parameters["TimeStamp"].SetValue(time.TotalGameTime.Milliseconds);

                    //fx.Parameters["DiffuseDirection"].SetValue(Wargames.DiffuseDirection);
                    //fx.Parameters["DiffuseColor"].SetValue(Wargames.DiffuseColor);
                    //fx.Parameters["DiffuseLevel"].SetValue(Wargames.DiffuseLevel);
                }
                mesh.Draw();
            } 
        }
        public abstract void UpdateStructure(Input input, GameTime time);        
    }
}
